package com.hp.bon.sgw.util.dcc;

import com.gadberry.utility.expression.Expression;
import com.hp.bon.security.config.SecurityConfigManager;
import com.hp.bon.sgw.Constants;
import com.hp.bon.sgw.Constants.MessageType;
import com.hp.bon.sgw.bean.XmlMessage;
import com.hp.bon.sgw.core.CallParam;
import com.hp.bon.sgw.domain.BusinessRecord;
import com.hp.bon.sgw.domain.ConvMapInfo;
import com.hp.bon.sgw.domain.MessageDetail;
import com.hp.bon.sgw.domain.MsgTransRecord;
import com.hp.bon.sgw.start.SpringContext;
import com.hp.bon.sgw.threads.MessageDetailCacheManager;
import com.hp.ocs.diameter.DiameterUtils;
import com.hp.ocs.diameter.message.*;
import com.hp.ocs.diameter.message.dictionary.AvpType;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

public class DccAvpHelper {

	private static final Logger logger = LoggerFactory.getLogger(DccAvpHelper.class);

	public static final String OCS_SESSION_CTR_SVCTXID = "SessionCtr.OCS";
	public static DictionaryManager DCCDICMAN = DictionaryManager.getInstance();
	final int[] mandatoryAVPs = { Constants.DIAMETER_AVP_SESSION_ID, Constants.DIAMETER_AVP_ORIGIN_HOST, Constants.DIAMETER_AVP_ORIGIN_REALM, Constants.DIAMETER_AVP_DES_REALM, Constants.DIAMETER_AVP_AUTH_APP_ID, Constants.DIAMETER_AVP_CC_REQUEST_TYPE, Constants.DIAMETER_AVP_CC_REQUEST_NUMBER,
			Constants.DIAMETER_AVP_DEST_HOST, Constants.DIAMETER_AVP_ORIGIN_STATE_ID, Constants.DIAMETER_AVP_EVENT_TIMESTAMP, Constants.DIAMETER_AVP_SERVICE_INFOMATION, Constants.DIAMETER_AVP_SERVICE_CONTEXT_ID };

  public static String toString(Message msg, Map<String, ConvMapInfo> allAVPs)
  {
    MessageHeader header = msg.header();
    StringBuilder sb = new StringBuilder();
    sb.append(header.toString());
    sb.append(" Ver:").append(header.version());
    sb.append(" Len:").append(header.messageLength());
    sb.append(" Flag:");
    sb.append(header.isRequest() ? 'R' : '-');
    sb.append(header.isProxiable() ? 'P' : '-');
    sb.append(header.isError() ? 'E' : '-');
    sb.append(header.isRetransmit() ? 'T' : '-');

    if (header.isRetransmit())
      sb.append(" RetransmitCount:").append(msg.getRetransmittingCounter());
    sb.append("AVPs list:\n");
    fillAVPs(msg, sb, allAVPs);
    return sb.toString();
  }
	/**
	 * 生成带错误返回码的 SERVICE INFOMATION AVP
	 * 
	 * @param errCode
	 * @return
	 */
	public static AVP createServiceResultCodeAVPs(int errCode) {
		AVP_Unsigned32 errorCodeAVP = new AVP_Unsigned32(Constants.DIAMETER_AVP_SERVICE_RESULT_CODE, Constants.DIAMETER_VENDOR_CT, errCode);
		errorCodeAVP.setMandatory(true);
		AVP avpServiceInfomaiton = new AVP_Grouped(Constants.DIAMETER_AVP_SERVICE_INFOMATION, Constants.DIAMETER_VENDOR_3GPP, new AVP[] { errorCodeAVP });
		avpServiceInfomaiton.setMandatory(true);
		return avpServiceInfomaiton;
	}

	/**
	 * 将<Service-Information>AVP下的某个AVP转移到上面一层
	 * 
	 * @param msg
	 *            Message
	 * @param avpCode
	 *            需要转移的AVP 编码
	 */
	public static void moveUpServiceInfomationAVP(Message msg, int avpCode) {
		AVP srvInfAVP = null;
		List<AVP> allAVPS = msg.getAvpList();
		int srvInfAVPIndx = -1;
		for (int i = 0; i < allAVPS.size(); i++) {
			AVP theAVP = allAVPS.get(i);
			if (theAVP.code() == Constants.DIAMETER_AVP_SERVICE_INFOMATION && theAVP.vendorID() == Constants.DIAMETER_VENDOR_3GPP) {
				srvInfAVP = theAVP;
				srvInfAVPIndx = i;
				break;
			}
		}

		if (srvInfAVP == null) {
			return;
		}
		AVP[] avpGrps;
		try {
			avpGrps = new AVP_Grouped(srvInfAVP).queryAVPs();
		} catch (InvalidAVPLengthException e) {
			e.printStackTrace();
			return;
		}
		AVP foundAvp = null;
		ArrayList<AVP> newGrps = new ArrayList<AVP>(avpGrps.length);
		for (AVP avp : avpGrps) {
			if (avp.code() == avpCode && foundAvp == null) {
				foundAvp = avp;

			} else {// Copy to new Arry
				// System.out.println("add avp "+avp.code());
				newGrps.add(avp);
			}
		}
		if (foundAvp != null) {
			avpGrps = new AVP[newGrps.size()];
			newGrps.toArray(avpGrps);
			srvInfAVP = new AVP_Grouped(Constants.DIAMETER_AVP_SERVICE_INFOMATION, Constants.DIAMETER_VENDOR_3GPP, avpGrps);
			srvInfAVP.setMandatory(true);
			msg.remove(srvInfAVPIndx);
			msg.add(srvInfAVP);
			msg.add(foundAvp);
		}

	}

	public static void moveIntoServiceInfomationAVP(Message msg, int avpCode) {
		AVP srvInfAVP = null;
		List<AVP> allAVPS = msg.getAvpList();
		int foundAVPIndex = -1;
		int foundSrvAVPIndex = -1;
		AVP foundAVP = null;
		for (int i = 0; i < allAVPS.size(); i++) {
			AVP theAVP = allAVPS.get(i);
			if (theAVP.code() == Constants.DIAMETER_AVP_SERVICE_INFOMATION && theAVP.vendorID() == Constants.DIAMETER_VENDOR_3GPP && srvInfAVP == null) {
				srvInfAVP = theAVP;
				foundSrvAVPIndex = i;
			} else if (theAVP.code() == avpCode && foundAVP == null) {
				foundAVPIndex = i;
				foundAVP = theAVP;
			}
			if (srvInfAVP != null && foundAVP != null) {
				break;
			}
		}
		if (foundAVP == null) {
			return;
		}
		if (srvInfAVP == null) {// 没有的时候,重新创建
								// Service Information
			srvInfAVP = new AVP_Grouped(Constants.DIAMETER_AVP_SERVICE_INFOMATION, Constants.DIAMETER_VENDOR_3GPP, new AVP[] { foundAVP });
			srvInfAVP.setMandatory(true);
			msg.remove(foundAVPIndex);
			msg.add(srvInfAVP);
			return;
		}

		AVP[] avpGrps;
		try {
			avpGrps = new AVP_Grouped(srvInfAVP).queryAVPs();
		} catch (InvalidAVPLengthException e) {
			e.printStackTrace();
			return;
		}
		AVP[] newAvpGrps = new AVP[avpGrps.length + 1];
		System.arraycopy(avpGrps, 0, newAvpGrps, 0, avpGrps.length);
		newAvpGrps[newAvpGrps.length - 1] = foundAVP;
		srvInfAVP = new AVP_Grouped(Constants.DIAMETER_AVP_SERVICE_INFOMATION, Constants.DIAMETER_VENDOR_3GPP, newAvpGrps);
		srvInfAVP.setMandatory(true);
		if (foundSrvAVPIndex < foundAVPIndex) {
			msg.remove(foundSrvAVPIndex);
			msg.remove(foundAVPIndex - 1);
		} else {
			msg.remove(foundAVPIndex);
			msg.remove(foundSrvAVPIndex - 1);
		}
		msg.add(srvInfAVP);
	}

	/**
	 * 
	 * @param dccMsg
	 * @param avpStrName
	 *            如Service-Information.Service_Result_Code，父子之间用"/"分隔
	 * @return
	 */
	public static String getAVPValue(Message dccMsg, String avpStrName, final Map<String, ConvMapInfo> allAVPMap) {
		StringBuilder retAVPName = new StringBuilder();
		AVP avp = getAVP(dccMsg, avpStrName, allAVPMap, retAVPName);
		if (avp == null) {
			return null;
		} else {
			ConvMapInfo convInf = allAVPMap.get(retAVPName.toString());
			try {
				return getAvpValue(convInf.getTypeCode(), avp);
			} catch (Exception e) {
				return null;
			}
		}
	}

	/**
	 * 得到某个AVP ，可以实现查找类似Service-Information/Service_Result_Code的 下级AVP
	 * 
	 * @param dccMsg
	 * @param avpStrName
	 * @param allAVPMap
	 * @return
	 */
	public static AVP getAVP(Message dccMsg, String avpStrName, final Map<String, ConvMapInfo> allAVPMap, StringBuilder returnAVPName) {
		String[] namePaths = avpStrName.split("/");
		AVP parentAVP = null;
		try {
			for (String avpName : namePaths) {
				ConvMapInfo convInf = allAVPMap.get(avpName);
				if (convInf == null) {
					return null;
				}
				AVP theAVP = null;
				if (parentAVP == null) {
					theAVP = dccMsg.find(convInf.getAvpCode(), convInf.getVenderID());

				} else {// 是child AVP
					theAVP = new AVP_Grouped(parentAVP).find(convInf.getAvpCode(), convInf.getVenderID());
				}
				if (theAVP == null) {
					return null;
				}
				if (convInf.getTypeCode() == ConvMapInfo.AVP_Grouped) {
					parentAVP = theAVP;
				}
				// 判断是否是到最后一级
				String theName = namePaths[namePaths.length - 1];
				if (convInf.getAvpName().equals(theName)) {
					returnAVPName.append(theName);
					return theAVP;
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		// System.out.println("cant find avp " + avpStrName + " dcc msg "
		// + dccMsg.getDictionary().toString());
		return null;
	}

	/**
	 * 从DCC消息中获取指定的AVP属性值
	 * 
	 * @param fieldName
	 * @return
	 */
	public static Map<String, String> converDCCMsgLeafField(Message dccMsg, Set<String> fields, Map<String, ConvMapInfo> allAVPMap) {
		Map<String, String> resulMap = new HashMap<String, String>(fields.size());
		for (String avpName : fields) {
			String value = getAVPValue(dccMsg, avpName, allAVPMap);
			if (value != null) {
				resulMap.put(avpName, value);
			}
		}
		return resulMap;
	}

  private static void fillAVPs(Message _message, StringBuilder sb, Map<String, ConvMapInfo> avpDefMap) {
    if (_message.avps() == null)
      return;
    for (AVP avp : _message.avps()) {
      boolean success;
      try {
        success = fillAVP(sb, avp, 0, avpDefMap);
      }
      catch (Exception e)
      {
        success = false;
      }
      if (!success)
      {
        sb.append(" parse failed,dump:\n");
      }

      sb.append('\n');
    }
  }

  private static boolean fillAVP(StringBuilder sb, AVP avp, int recursiveLevel, Map<String, ConvMapInfo> avpDefMap) throws InvalidAVPLengthException, InvalidAddressTypeException {
    if (avp == null)
      return false;
    for (int i = 0; i < recursiveLevel; i++) {
      sb.append('\t');
    }
    if (avp.isVendorSpecific()) {
      sb.append("Vendor:").append(avp.vendorID()).append("-");
    }
    ConvMapInfo avpDef = (ConvMapInfo)avpDefMap.get(avp.vendorID() + ":" + avp.code());
    if (avpDef == null) {
      sb.append("can't find avp def for avp ");
    }
    String name = avpDef != null ? avpDef.getAvpName() : "UnknownAVP";
    sb.append(name).append('(').append(avp.code()).append(":");
    if (avp.isVendorSpecific())
      sb.append('V');
    if (avp.isMandatory())
      sb.append('M');
    if (avp.isPrivate())
      sb.append('P');
    sb.append(")");
    if (avpDef == null)
      return false;
    sb.append('[').append(avpDef.getAvpType()).append("]=");
    return fillAvpValue(avpDef.getTypeCode(), avp, sb, recursiveLevel, avpDefMap);
  }

	public static String getAvpValue(int format, AVP avp) throws InvalidAVPLengthException, InvalidAddressTypeException {
		switch (format) {
		case ConvMapInfo.AVP_INT32: {
			AVP_Integer32 avpi = new AVP_Integer32(avp);
			int value = avpi.queryValue();
			return Integer.toString(value);
		}

		case ConvMapInfo.AVP_INT64: {
			AVP_Integer64 avpi = new AVP_Integer64(avp);
			long value = avpi.queryValue();
			return Long.toString(value);
		}

		case ConvMapInfo.AVP_U32: {
			AVP_Unsigned32 avpi = new AVP_Unsigned32(avp);
			int value = avpi.queryValue();
			return Integer.toString(value);
		}
		case ConvMapInfo.AVP_U64: {
			AVP_Unsigned64 avpi = new AVP_Unsigned64(avp);
			long value = avpi.queryValue();
			return Long.toString(value);
		}
		case ConvMapInfo.AVP_F32: {
			AVP_Float32 avpi = new AVP_Float32(avp);
			return Float.toString(avpi.queryValue());
		}
		case ConvMapInfo.AVP_F64: {
			AVP_Float64 avpi = new AVP_Float64(avp);
			return Double.toString(avpi.queryValue());
		}
		case ConvMapInfo.AVP_UTF8String: {
			AVP_UTF8String avpi = new AVP_UTF8String(avp);
			return avpi.queryValue();
		}
		case ConvMapInfo.AVP_OctetString: {
			AVP_OctetString avpi = new AVP_OctetString(avp);
			return avpi.queryValueAsString();
		}
		case ConvMapInfo.AVP_Grouped: {
			return null;
		}
		case ConvMapInfo.AVP_Address: {
			AVP_Address avpi = new AVP_Address(avp);
			return avpi.queryAddress().toString();
		}
		case ConvMapInfo.AVP_Time: {
			AVP_Time avpi = new AVP_Time(avp);
			return avpi.queryDate().toString();
		}
		case ConvMapInfo.AVP_Enumerated:
			AVP_Integer32 avpi = new AVP_Integer32(avp);
			int i = avpi.queryValue();
			return Integer.toString(i);
		default:
			// System.out.println("cant recongize type " + format + " of avp "
			// + avp.code());
			return null;
		}
	}
  private static boolean fillAvpValue(int format, AVP avp, StringBuilder sb, int recursiveLevel, Map<String, ConvMapInfo> avpDefMap) throws InvalidAVPLengthException, InvalidAddressTypeException
  {
    switch (format) {
    case ConvMapInfo.AVP_INT32: {
      AVP_Integer32 avpi = new AVP_Integer32(avp);
      int value = avpi.queryValue();
      sb.append(value);
      sb.append("[0x").append(Integer.toHexString(value).toUpperCase()).append(']');
      break;
    }
    case ConvMapInfo.AVP_INT64: {
      AVP_Integer64 avpi = new AVP_Integer64(avp);
      long value = avpi.queryValue();
      sb.append(value);
      sb.append("[0x").append(Long.toHexString(value).toUpperCase()).append(']');
      break;
    }
    case ConvMapInfo.AVP_U32: {
      AVP_Unsigned32 avpi = new AVP_Unsigned32(avp);
      int value = avpi.queryValue();
      sb.append(value);
      sb.append("[0x").append(Integer.toHexString(value).toUpperCase()).append(']');
      break;
    }
    case ConvMapInfo.AVP_U64: {
      AVP_Unsigned64 avpi = new AVP_Unsigned64(avp);
      long value = avpi.queryValue();
      sb.append(value);
      sb.append("[0x").append(Long.toHexString(value).toUpperCase()).append(']');

      break;
    }
    case ConvMapInfo.AVP_F32: {
      AVP_Float32 avpi = new AVP_Float32(avp);
      sb.append(avpi.queryValue());

      break;
    }
    case ConvMapInfo.AVP_F64: {
      AVP_Float64 avpi = new AVP_Float64(avp);
      sb.append(avpi.queryValue());

      break;
    }
    case ConvMapInfo.AVP_UTF8String: {
      AVP_UTF8String avpi = new AVP_UTF8String(avp);
      sb.append(avpi.queryValue());

      break;
    }
    case ConvMapInfo.AVP_OctetString: {
      AVP_OctetString avpi = new AVP_OctetString(avp);
      sb.append(avpi.queryValueAsString());

      break;
    }
    case ConvMapInfo.AVP_Grouped: {
      sb.append('\n');

      AVP_Grouped avpg = new AVP_Grouped(avp);
      recursiveLevel++;
      for (AVP avp1 : avpg.queryAVPs()) {
        if (!fillAVP(sb, avp1, recursiveLevel, avpDefMap))
          return false;
        sb.append('\n');
      }

      break;
    }
    case ConvMapInfo.AVP_Address: {
      AVP_Address avpi = new AVP_Address(avp);
      sb.append(avpi.queryAddress());

      break;
    }
    case ConvMapInfo.AVP_Time:{
      AVP_Time avpi = new AVP_Time(avp);
      sb.append(avpi.queryDate());

      break;
    }
    case ConvMapInfo.AVP_Enumerated: 
      return fillAvpEnumeratedValue(avp, sb);
    default:
      return false;
    }
    return true;
  }

  private static boolean fillAvpEnumeratedValue(AVP avp, StringBuilder sb) throws InvalidAVPLengthException {
    AVP_Integer32 avpi = new AVP_Integer32(avp);
    int i = avpi.queryValue();
    sb.append(i);
    return true;
  }

  public static void creatComMessageBeforCCR(Message message, String sessionID, String serviceCtxID) {
		message.header().setRequest(true);
		message.header().setProxiable(true);
		message.header().setApplicationID(Constants.DIAMETER_APPLICATION_CREDIT_CONTROL);
		message.header().setCommandCode(Constants.DIAMETER_CMD_CCR);

		message.add(new AVP_UTF8String(Constants.DIAMETER_AVP_SESSION_ID, sessionID));
		AVP serviceContextId = new AVP_UTF8String(Constants.DIAMETER_AVP_SERVICE_CONTEXT_ID, serviceCtxID);
		serviceContextId.setMandatory(true);
		message.add(serviceContextId);

		String destRealm = DccAvpHelper.getRealmPart(serviceCtxID);
		AVP dReaalm = new AVP_OctetString(Constants.DIAMETER_AVP_DES_REALM, destRealm);
		dReaalm.setMandatory(true);
		message.add(dReaalm);

		AVP appId = new AVP_Unsigned32(Constants.DIAMETER_AVP_AUTH_APP_ID, 4);
		appId.setMandatory(true);
		message.add(appId);

		AVP enventTime = new AVP_Time(Constants.DIAMETER_AVP_EVENT_TIMESTAMP, new Date());
		enventTime.setMandatory(true);
		message.add(enventTime);
  }

	public static void logMessageDetail(CallParam callParam, String toPeerHostId, Message newMessage) {
		MessageDetail md = new MessageDetail();
		md.setBusinessCallId(callParam.getBussinessCallId());
		md.setSessionId(callParam.getSessionId());
		md.setServiceContextId(callParam.getServiceContextId());
		md.setMessageType(MessageType.CCR);
		md.setOpType("send");
		md.setHostId(toPeerHostId);
		md.setMsgTime(new Date(newMessage._rt0));
		md.setDetails(newMessage.getDictionary().toString());
		MessageDetailCacheManager.getInstance().add(md);

	}

	// /**
	// * 生成一般性的CCA反馈发送请求
	// *
	// * @param reqMsg
	// * 请求消息
	// * @param resultCode
	// * 失败代码
	// * @return SGWReplyMsgSendReq
	// */
	// public static SGWReplyMsgSendReq genGenelCCASendReq(Message reqMsg, Node
	// receiverNode, int resultCode, boolean isAddOurOriginAVP) {
	// Message answerMsg = DccAvpHelper.genAnswerForReq(reqMsg);
	// answerMsg.add(new AVP_Unsigned32(ProtocolConstants.DI_RESULT_CODE,
	// resultCode));
	// return new SGWReplyMsgSendReq(answerMsg, receiverNode,
	// isAddOurOriginAVP);
	// }

	/**
	 * 返回AVP_RESULT_CODE ，如果出错，返回-1
	 * 
	 * @param cca
	 * @return AVP_RESULT_CODE
	 */
	public static int getCCAMessageResultCode(Message cca) {
		int resultCode = -1;
		AVP result_code = cca.find(Constants.DIAMETER_AVP_RESULT_CODE);
		if (result_code != null) {
			try {
				resultCode = new AVP_Unsigned32(result_code).queryValue();
			} catch (InvalidAVPLengthException e) {
				// ignore
			}
		}
		return resultCode;
	}

	public static String getMessageOriginalHost(Message message) {
		AVP originalHostAVP = message.find(Constants.DIAMETER_AVP_ORIGIN_HOST);
		if (originalHostAVP != null) {
			return AVP_UTF8String.queryValue(originalHostAVP);
		}
		return null;
	}

	public static String getMessageDestHost(Message message) {
		AVP hostAVP = message.find(Constants.DIAMETER_AVP_DEST_HOST);
		if (hostAVP != null) {
			return AVP_UTF8String.queryValue(hostAVP);
		}
		return null;
	}

  public static int getCCAMessageServiceResultCode(Message cca)
  {
    int result = -1;
    try {
      AVP[] avps = new AVP[cca.getAvpList().size()];
      AVP avp = getAVP((AVP[])cca.getAvpList().toArray(avps), 20631);
      if (avp != null) {
        result = new AVP_Unsigned32(avp).queryValue();
      }
      else
      {
        AVP sessionIdAvp = getAVP((AVP[])cca.getAvpList().toArray(avps), 263);
        if (sessionIdAvp != null)
        {
          String sessionId = new AVP_UTF8String(sessionIdAvp).queryValue();
          logger.warn("There is no Service_Result_Code avp in session " + sessionId);
        }
      }
    }
    catch (Exception e) {
      String sessionId2 = null;
      try
      {
        AVP[] avps2 = new AVP[cca.getAvpList().size()];
        AVP sessionIdAvp2 = getAVP((AVP[])cca.getAvpList().toArray(avps2), 263);
        if (sessionIdAvp2 != null)
        {
          sessionId2 = new AVP_UTF8String(sessionIdAvp2).queryValue();
        }
        logger.warn("Exception occur when find Service_Result_Code avp from CCA,sessionId is " + sessionId2 + "." + e.getMessage(), e);
        e.printStackTrace();
      }
      catch (Exception ee)
      {
        logger.warn("Exception occur when get sessionId from CCA." + ee.getMessage(), ee);
        ee.printStackTrace();
      }
    }

    return result;
  }

	// /**
	// * 生成一般性的CCA转发发送请求
	// *
	// * @param reqMsg
	// * 请求消息
	// * @return SGWReplyMsgSendReq
	// */
	// public static SGWReplyMsgSendReq genGenelFowradCCASendReq(Message ccaMsg,
	// Node receiverNode, boolean isAddOurOriginAVP) {
	//
	// SGWReplyMsgSendReq sendReq = new SGWReplyMsgSendReq(ccaMsg, receiverNode,
	// isAddOurOriginAVP);
	// return sendReq;
	// }

	/**
	 * 从HostID或者ServiceContextID中获取Realm部分的值
	 * 
	 * @param serviceCtxID
	 * @return
	 */
	public static String getRealmPart(String targetID) {
		return targetID.substring(targetID.indexOf('@') + 1);
	}

	public static String getMessageUniqueID(String sessionID, Message msg) {
		String msgID = sessionID;
		int reqNumber = getMessageCCRequestNumber(msg);
		if (reqNumber != -1 && reqNumber != 0) {
			msgID = msgID + Constants.UniqueMsgIdSpilt + reqNumber;
		}
		return msgID;
	}

	/**
	 * 返回CC-Request-Number，如果出错，返回-1
	 * 
	 * @param cca
	 * @return CC-Request-Number
	 */
	public static int getMessageCCRequestNumber(Message msg) {
		int result = -1;
		AVP reqNumber = msg.find(Constants.DIAMETER_AVP_CC_REQUEST_NUMBER);
		if (reqNumber != null) {
			try {
				result = new AVP_Unsigned32(reqNumber).queryValue();
			} catch (InvalidAVPLengthException e) {
				throw new RuntimeException(e);
			}
		}
		return result;
	}

	/**
	 * 
	 * 
	 * @param cca
	 * @return CC-Request-Number
	 */
	public static void processMessgeForwardInfos(Message msg, MsgTransRecord dccTransRec) {
		List<AVP> avpList = msg.getAvpList();
		String rs;
		for (AVP avp : avpList) {
			try {
				switch (avp.code()) {
				case Constants.DIAMETER_AVP_Route_Record:
					rs = AVP_UTF8String.queryValue(avp);
					String routeRecord = dccTransRec.getRouteRecord();
					if (routeRecord != null && routeRecord.length() > 0) {
						routeRecord = routeRecord + "+" + rs;
					} else {
						routeRecord = rs;
					}
					dccTransRec.setRouteRecord(routeRecord);
					break;
				case Constants.DIAMETER_AVP_Forward_Info:
					AVP_Grouped forwardInfoGrouped;
					forwardInfoGrouped = new AVP_Grouped(avp);

					AVP selfHost = forwardInfoGrouped.find(Constants.DIAMETER_AVP_SELF_HOST, Constants.DIAMETER_VENDOR_CT);
					String foInfo = "";
					if (null != selfHost) {
						foInfo = (new AVP_UTF8String(selfHost)).queryValue();
					}
					foInfo = foInfo + ":";
					AVP downstreamHost = forwardInfoGrouped.find(Constants.DIAMETER_AVP_DOWNSTREAM_HOST, Constants.DIAMETER_VENDOR_CT);
					if (null != downstreamHost) {
						foInfo = foInfo + (new AVP_UTF8String(downstreamHost)).queryValue();
					}
					AVP responseTime = forwardInfoGrouped.find(Constants.DIAMETER_AVP_RESPONSE_TIME, Constants.DIAMETER_VENDOR_CT);
					foInfo = foInfo + ":";
					if (null != responseTime) {
						foInfo = foInfo + (new AVP_Unsigned32(responseTime)).queryValue();
					}
					String forwardInfo = dccTransRec.getForwardInfo();
					if (null != forwardInfo && forwardInfo.length() > 0) {
						forwardInfo = forwardInfo + "+" + foInfo;
					} else {
						forwardInfo = foInfo;
					}
					dccTransRec.setForwardInfo(forwardInfo);
					break;
				}

			} catch (InvalidAVPLengthException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 
	 * 
	 * @param cca
	 * @return CC-Request-Number
	 */
	public static void processMessgeCommonInfos(Message msg, MsgTransRecord dccTransRec) {
		dccTransRec.setMsgLength(msg.header().messageLength());
		int commdCode = msg.header().commandCode();
		switch (commdCode) {
		case 258:// Re-Auth-Request
			dccTransRec.setMsgType(msg.header().isRequest() ? MsgTransRecord.MSG_TYPE_RAR : MsgTransRecord.MSG_TYPE_RAA);
			break;
		case 274:// Abort-Session-Request
			dccTransRec.setMsgType(msg.header().isRequest() ? MsgTransRecord.MSG_TYPE_ASR : MsgTransRecord.MSG_TYPE_ASA);
			break;
		case 272:
			dccTransRec.setMsgType(msg.header().isRequest() ? MsgTransRecord.MSG_TYPE_CCR : MsgTransRecord.MSG_TYPE_CCA);
			break;
		default:
			dccTransRec.setMsgType(commdCode + "");
		}

		List<AVP> avpList = msg.getAvpList();
		for (AVP avp : avpList) {
			try {
				switch (avp.code()) {
				case Constants.DIAMETER_AVP_CC_REQUEST_NUMBER:
					int ccNum = AVP_Unsigned32.queryValue(avp);
					dccTransRec.setCcRequestNumber(ccNum);
					break;
				case Constants.DIAMETER_AVP_ORIGIN_HOST:
					dccTransRec.setOriginHost(AVP_UTF8String.queryValue(avp));
					break;
				case Constants.DIAMETER_AVP_DEST_HOST:
					dccTransRec.setDestHost(AVP_UTF8String.queryValue(avp));
					break;
				case Constants.DIAMETER_AVP_DES_REALM:
					dccTransRec.setDestRealm(AVP_UTF8String.queryValue(avp));
					break;
				case Constants.DIAMETER_AVP_RESULT_CODE:
					dccTransRec.setResultCode(AVP_Unsigned32.queryValue(avp));
					break;
				case Constants.DIAMETER_AVP_SERVICE_RESULT_CODE:
					dccTransRec.setServiceResultCode(AVP_Unsigned32.queryValue(avp));
					break;
				}

			} catch (InvalidAVPLengthException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 从ServiceContextID中获取不包含Realm部分的值
	 * 
	 * @param serviceCtxID
	 * @return
	 */
	public static String getCapability(String targetID) {
		return targetID.substring(0, targetID.indexOf('@'));
	}

	/**
	 * 从ServiceContextID中获取不包含省代码的域部分
	 * 
	 * @param srvCtxID
	 * @return
	 */
	public static String getRealmWithoutAreaCode(String srvCtxID) {
		int atPos = srvCtxID.indexOf("@");
		int post1 = srvCtxID.indexOf(".", atPos);
		int post2 = srvCtxID.indexOf(".", post1);
		return srvCtxID.substring(post2 + 1);
	}

	/**
	 * 得到ServiceCtxID中的省代码
	 * 
	 * @param srvCtxID
	 * @return
	 */
	public static String getArea(String srvCtxID) {
		int pos1 = srvCtxID.indexOf("@");
		int pos2 = srvCtxID.indexOf(".", pos1);
		return srvCtxID.substring(pos1 + 1, pos2);

	}

	public static String replaceSrvCtxID(String oldSrvCtxID, String newRealmWithoutArea) {
		String serviceCtxID = DccAvpHelper.getCapability(oldSrvCtxID) + "@" + DccAvpHelper.getArea(oldSrvCtxID) + "." + newRealmWithoutArea;
		return serviceCtxID;
	}

	public static void replaceSrvCtxID(Message msg, String newSrvCtxID) {
		Iterator<AVP> msgAVPItors = msg.iterator();
		while (msgAVPItors.hasNext()) {
			AVP avp = msgAVPItors.next();
			if (avp.code() == Constants.DIAMETER_AVP_SERVICE_CONTEXT_ID) {
				msgAVPItors.remove();
				break;
			}
		}

		// msg.add(new AVP_UTF8String(Constants.DIAMETER_AVP_SERVICE_CONTEXT_ID,
		// DIAMETER_VENDOR_3GPP, newSrvCtxID));
		AVP serviceContextId = new AVP_UTF8String(Constants.DIAMETER_AVP_SERVICE_CONTEXT_ID, newSrvCtxID);
		serviceContextId.setMandatory(true);
		msg.add(serviceContextId);
	}

	public static void replaceDestinationRealm(Message msg, String newDestinationRealm) {
		Iterator<AVP> msgAVPItors = msg.iterator();
		while (msgAVPItors.hasNext()) {
			AVP avp = msgAVPItors.next();
			if (avp.code() == Constants.DIAMETER_AVP_DES_REALM) {
				msgAVPItors.remove();
				break;
			}
		}

		// msg.add(new AVP_UTF8String(Constants.DIAMETER_AVP_SERVICE_CONTEXT_ID,
		// DIAMETER_VENDOR_3GPP, newSrvCtxID));
		AVP serviceContextId = new AVP_OctetString(Constants.DIAMETER_AVP_DES_REALM, newDestinationRealm);
		serviceContextId.setMandatory(true);
		msg.add(serviceContextId);

	}

	/**
	 * replace result code or service result code
	 * 
	 * @param msg
	 * @param resultCode
	 * @param avpCode
	 */
	public static void replaceResultCode(Message msg, int resultCode, int avpCode) {
		if (resultCode == -1)
			return;
		Iterator<AVP> msgAVPItors = msg.iterator();
		while (msgAVPItors.hasNext()) {
			AVP avp = msgAVPItors.next();
			if (avp.code() == avpCode) {
				msgAVPItors.remove();
				break;
			}
		}
		if (avpCode == Constants.DIAMETER_AVP_RESULT_CODE)
			msg.add(new AVP_Unsigned32(Constants.DIAMETER_AVP_RESULT_CODE, resultCode));
		else if (avpCode == Constants.DIAMETER_AVP_SERVICE_RESULT_CODE)
			msg.add(new AVP_Unsigned32(Constants.DIAMETER_AVP_RESULT_CODE, Constants.DIAMETER_VENDOR_CT, resultCode));

	}

  public static Message genAnswerForReq(Message request)
  {
    Message answerMsg = new Message();
    answerMsg.prepareResponse(request);

    request.getDictionary().prepareResponseAVP(answerMsg);
    return answerMsg;
  }

	/**
	 * 生成SERVICE_INFOMATION AVP和业务返回码
	 * 
	 * @return
	 */
	public static AVP genDefaultServiceResultAVP(int srvRstCode) {
		AVP serviceResult = new AVP_Unsigned32(Constants.DIAMETER_AVP_SERVICE_RESULT_CODE, Constants.DIAMETER_VENDOR_CT, srvRstCode);
		serviceResult.setMandatory(true);
		AVP avpServiceInfomaiton = new AVP_Grouped(Constants.DIAMETER_AVP_SERVICE_INFOMATION, Constants.DIAMETER_VENDOR_3GPP, new AVP[] { serviceResult });
		avpServiceInfomaiton.setMandatory(true);
		return avpServiceInfomaiton;
	}

	/**
	 * 复制Message,复制其中的AVP
	 * 
	 * @param fromMsg
	 * @param toMsg
	 */
	public static void copyMessageAVP(Message fromMsg, Message toMsg) {
		// Iterator<AVP> avpIteror = fromMsg.getAvpList().iterator();
		// while (avpIteror.hasNext()) {
		// toMsg.add(avpIteror.next());
		// }
		toMsg.add(fromMsg.getAvpList());
	}

	public static void copyMessageHeader(MessageHeader fromHeader, MessageHeader toHeader) {
		toHeader.setProxiable(fromHeader.isProxiable());
		toHeader.setApplicationID(fromHeader.applicationID());
		toHeader.setRequest(fromHeader.isRequest());
		toHeader.setCommandCode(fromHeader.commandCode());
		toHeader.setHopByHopIdentifier(fromHeader.hopByHopID());
		toHeader.setEndToEndIdentifier(fromHeader.endToEndID());
		toHeader.setRetransmit(fromHeader.isRetransmit());
		toHeader.setProxiable(fromHeader.isProxiable());
		toHeader.setError(fromHeader.isError());
	}

	/**
	 * 生成上报拥塞的消息AVP
	 * 
	 * @param neNode
	 * @param routes
	 * @param online
	 * @return
	 */
	public static AVP generateCongestionAVP(String ourHostID, int congestionLevel) {

		AVP netHost = new AVP_UTF8String(Constants.DIAMETER_AVP_NE_HOST, Constants.DIAMETER_VENDOR_CT, ourHostID);
		AVP netType = new AVP_Unsigned32(Constants.DIAMETER_AVP_NE_TYPE, Constants.DIAMETER_VENDOR_CT, Constants.DIAMETER_AVP_NE_TYPE__BUSINESSNE);

		AVP congestionLevelAVP = new AVP_Unsigned32(Constants.DIAMETER_AVP_Congestion_Level, Constants.DIAMETER_VENDOR_CT, congestionLevel);
		AVP_Grouped neInformation = new AVP_Grouped(Constants.DIAMETER_AVP_NE_INFOMATION, Constants.DIAMETER_VENDOR_CT, new AVP[] { netHost, netType, congestionLevelAVP });
		neInformation.setMandatory(true);

		AVP_Grouped netCtrlInformation = new AVP_Grouped(Constants.DIAMETER_AVP_NET_CTRL_INFOMATION, Constants.DIAMETER_VENDOR_CT, new AVP[] { neInformation });
		netCtrlInformation.setMandatory(true);

		// Service Information
		AVP_Grouped serviceInformation = new AVP_Grouped(Constants.DIAMETER_AVP_SERVICE_INFOMATION, Constants.DIAMETER_VENDOR_3GPP, new AVP[] { netCtrlInformation });
		serviceInformation.setMandatory(true);
		return serviceInformation;
	}

	/**
	 * 将CCA的AVP包装在SGW_DATA_ROOT这个Group AVP 中返回
	 * 
	 * @param cca
	 * @return SGW_DATA_ROOT AVP
	 */
	public static AVP_Grouped createSGWRootAVPFromMessage(Message dccMsg) {
		// List<AVP> avpList = new ArrayList<AVP>(dccMsg.size());
		// for (AVP avp : dccMsg.getAvpList()) {
		// int avpCode = avp.code();
		// boolean exclude = (avpCode == Constants.DIAMETER_AVP_SESSION_ID)
		// || (avpCode == Constants.DIAMETER_AVP_ORIGIN_HOST)
		// || (avpCode == Constants.DIAMETER_AVP_ORIGIN_REALM)
		// || (avpCode == Constants.DIAMETER_AVP_RESULT_CODE)
		// || (avpCode == Constants.DIAMETER_AVP_DEST_HOST)
		// || (avpCode == Constants.DIAMETER_AVP_DES_REALM)
		// || (avpCode == Constants.DIAMETER_AVP_AUTH_APP_ID)
		// || (avpCode == Constants.DIAMETER_AVP_Acct_APP_ID)
		// || (avpCode == Constants.DIAMETER_AVP_EVENT_TIMESTAMP)
		// || (avpCode == Constants.DIAMETER_AVP_SERVICE_CONTEXT_ID)
		// || (avpCode == Constants.DIAMETER_AVP_ORIGIN_STATE_ID)
		// || (avpCode == Constants.DIAMETER_AVP_Termination_Cause)
		// || (avpCode == Constants.DIAMETER_AVP_Route_Record)
		// || (avpCode == Constants.DIAMETER_AVP_Proxy_Info)
		// || (avpCode == Constants.DIAMETER_AVP_Forward_Info);
		// if (!exclude) {
		// avpList.add(avp);
		// }
		// }

		List<AVP> avpList = dccMsg.getAvpList();// 测试环境用
		AVP_Grouped sgwRootAVP = new AVP_Grouped(Constants.SGW_DATA_ROOT_AVP, Constants.DIAMETER_VENDOR_CT, avpList.toArray(new AVP[avpList.size()]));
		return sgwRootAVP;
	}

	/**
	 * 将转换结果的AVP 加入到DCC消息体中，如果convertAVP 是虚拟的SGW_DATA_ROOT，则添加其Children
	 * 否则，添加这个AVP本身
	 * 
	 * @param convertAVP
	 * @param dccMsg
	 */
	public static void addBusinessAVPs(AVP convertAVP, Message dccMsg) {
		if (convertAVP.code() == Constants.SGW_DATA_ROOT_AVP) {
			AVP[] children;
			try {
				children = new AVP_Grouped(convertAVP).queryAVPs();
			} catch (InvalidAVPLengthException e) {
				throw new RuntimeException(e);
			}
			for (AVP child : children) {
				dccMsg.add(child);
			}
		} else {
			dccMsg.add(convertAVP);
		}
	}

  public static String createNECapabilityRegMessage(Message message, Collection<String> capabilites, String serviceCtxID, String ourHostID)
  {
    String sessionID = DiameterUtils.makeSessionID(ourHostID);
    creatComMessageBeforCCR(message, sessionID, serviceCtxID);
    AVP netHost = new AVP_UTF8String(80024, 81000, ourHostID);
    AVP netType = new AVP_Unsigned32(80029, 81000, 2);

    boolean needActivePassword = SpringContext.getInstance().getConfigService().getBooleanValue("sgw.activepassword", false);
    AVP_Grouped netInformation = null;
    if (needActivePassword) {
      String[] key = SecurityConfigManager.getInstance().getActiveKey();
      AVP keyVersion = new AVP_UTF8String(80076, 81000, key[0]);
      AVP authCode = new AVP_UTF8String(80077, 81000, key[1]);
      netInformation = new AVP_Grouped(80021, 81000, new AVP[] { netHost, netType, keyVersion, authCode });
    } else {
      netInformation = new AVP_Grouped(80021, 81000, new AVP[] { netHost, netType });
    }

    netInformation.setMandatory(true);
    AVP_Grouped netCtrlInformation = null;

    if ((capabilites != null) && (!capabilites.isEmpty())) {
      int size = capabilites.isEmpty() ? 0 : capabilites.size();

      AVP_UTF8String[] serviceContextIds = new AVP_UTF8String[size];
      int i = 0;
      for (String cap : capabilites) {
        AVP serviceContextId = new AVP_UTF8String(461, cap);
        serviceContextId.setMandatory(true);
        serviceContextIds[(i++)] = ((AVP_UTF8String)serviceContextId);
      }

      AVP_Grouped serviceContextInfo = new AVP_Grouped(80031, 81000, serviceContextIds);
      serviceContextInfo.setMandatory(true);

      netCtrlInformation = new AVP_Grouped(80020, 81000, new AVP[] { netInformation, serviceContextInfo });
    } else {
      netCtrlInformation = new AVP_Grouped(80020, 81000, new AVP[] { netInformation });
    }
    netCtrlInformation.setMandatory(true);

    AVP_Grouped serviceInformation = new AVP_Grouped(873, 10415, new AVP[] { netCtrlInformation });
    serviceInformation.setMandatory(true);
    message.add(serviceInformation);

    AVP originalHost = new AVP_UTF8String(264, ourHostID);
    AVP originalRealm = new AVP_UTF8String(296, getRealmPart(ourHostID));
    message.add(originalHost);
    message.add(originalRealm);

    return sessionID;
  }

	/**
	 * 将Service-Information中的某个AVP转换为另外一个AVP
	 * 
	 * @param msg
	 * @param sourceAvp
	 * @param targetAvp
	 */
	public static void changeServiceInfomationAVP(Message msg, int sourceAvp, String targetAvpName, String expression) throws Exception {
		AVP srvInfAVP = null;
		List<AVP> allAVPS = msg.getAvpList();
		int foundSrvAVPIndex = -1;
		for (int i = 0; i < allAVPS.size(); i++) {
			AVP theAVP = allAVPS.get(i);
			if (theAVP.code() == Constants.DIAMETER_AVP_SERVICE_INFOMATION && theAVP.vendorID() == Constants.DIAMETER_VENDOR_3GPP && srvInfAVP == null) {
				srvInfAVP = theAVP;
				foundSrvAVPIndex = i;
				break;
			}
		}

		if (srvInfAVP == null) {
			return;
		}
		AVP[] avpGrps;
		try {
			avpGrps = new AVP_Grouped(srvInfAVP).queryAVPs();
		} catch (InvalidAVPLengthException e) {
			e.printStackTrace();
			return;
		}
		DictionaryManager dic = DictionaryManager.getInstance();
		boolean replaced = false;
		for (int i = 0; i < avpGrps.length; i++) {
			AVP thAVP = avpGrps[i];
			if (thAVP.code() == sourceAvp) {
				int avpValue = dic.getAvpValueAsInt(thAVP);
				// found and replace
				expression = expression.replaceAll("value", avpValue + "");
				String newValue = Expression.evaluate(expression).toString();
				AVP newAVP = dic.makeAVP(targetAvpName, newValue);
				avpGrps[i] = newAVP;
				replaced = true;
				break;
			}
		}
		if (!replaced) {
			return;
		}
		srvInfAVP = new AVP_Grouped(Constants.DIAMETER_AVP_SERVICE_INFOMATION, Constants.DIAMETER_VENDOR_3GPP, avpGrps);
		msg.remove(foundSrvAVPIndex);
		msg.add(srvInfAVP);
	}

	public static AVP getAVP(AVP[] avps, int avpCode) {
		AVP returnAvp = null;
		for (AVP avp : avps) {
			if (avp.code() == avpCode) {
				returnAvp = avp;
				break;
			}
			try {
				AVP_Grouped avpG = new AVP_Grouped(avp);
				returnAvp = getAVP(avpG.queryAVPs(), avpCode);
			} catch (InvalidAVPLengthException e) {
				continue;
			}
		}
		return returnAvp;
	}

	/**
	 * 返回ParaFieldResult
	 * 
	 * @param cca
	 * @return ParaFieldResult
	 */
	public static String getCCAMessageParaFieldResult(Message cca) {
		String result = "";
		try {
			AVP[] avps = new AVP[cca.getAvpList().size()];
			AVP avp = getAVP(cca.getAvpList().toArray(avps), Constants.DIAMETER_AVP_Para_Field_Result);
			if (avp != null) {
				result = AVP_UTF8String.queryValue(avp);
			}
		} catch (Exception e) {
			// ignore
		}
		return result;
	}

	/**
	 * 
	 * 
	 * @param cca
	 * @return CC-Request-Number
	 */
	public static void processMessgeInfos(Message msg, MsgTransRecord dccTransRec) {
		dccTransRec.setMsgLength(msg.header().messageLength());
		int commdCode = msg.header().commandCode();
		switch (commdCode) {
		case 258:// Re-Auth-Request
			dccTransRec.setMsgType(msg.header().isRequest() ? MsgTransRecord.MSG_TYPE_RAR : MsgTransRecord.MSG_TYPE_RAA);
			break;
		case 274:// Abort-Session-Request
			dccTransRec.setMsgType(msg.header().isRequest() ? MsgTransRecord.MSG_TYPE_ASR : MsgTransRecord.MSG_TYPE_ASA);
			break;
		case 272:
			dccTransRec.setMsgType(msg.header().isRequest() ? MsgTransRecord.MSG_TYPE_CCR : MsgTransRecord.MSG_TYPE_CCA);
			break;
		default:
			dccTransRec.setMsgType(commdCode + "");
		}

		List<AVP> avpList = msg.getAvpList();
		String rs;
		for (AVP avp : avpList) {
			try {
				switch (avp.code()) {
				case Constants.DIAMETER_AVP_Route_Record:
					rs = (new AVP_UTF8String(avp)).queryValue();
					String routeRecord = dccTransRec.getRouteRecord();
					if (routeRecord != null && routeRecord.length() > 0) {
						routeRecord = routeRecord + "+" + rs;
					} else {
						routeRecord = rs;
					}
					dccTransRec.setRouteRecord(routeRecord);
					break;
				case Constants.DIAMETER_AVP_Forward_Info:
					AVP_Grouped forwardInfoGrouped;
					forwardInfoGrouped = new AVP_Grouped(avp);

					AVP selfHost = forwardInfoGrouped.find(Constants.DIAMETER_AVP_SELF_HOST, Constants.DIAMETER_VENDOR_CT);
					String foInfo = "";
					if (null != selfHost) {
						foInfo = (new AVP_UTF8String(selfHost)).queryValue();
					}
					foInfo = foInfo + ":";
					AVP downstreamHost = forwardInfoGrouped.find(Constants.DIAMETER_AVP_DOWNSTREAM_HOST, Constants.DIAMETER_VENDOR_CT);
					if (null != downstreamHost) {
						foInfo = foInfo + (new AVP_UTF8String(downstreamHost)).queryValue();
					}
					AVP responseTime = forwardInfoGrouped.find(Constants.DIAMETER_AVP_RESPONSE_TIME, Constants.DIAMETER_VENDOR_CT);
					foInfo = foInfo + ":";
					if (null != responseTime) {
						foInfo = foInfo + (new AVP_Unsigned32(responseTime)).queryValue();
					}
					String forwardInfo = dccTransRec.getForwardInfo();
					if (null != forwardInfo && forwardInfo.length() > 0) {
						forwardInfo = forwardInfo + "+" + foInfo;
					} else {
						forwardInfo = foInfo;
					}
					dccTransRec.setForwardInfo(forwardInfo);
					break;
				case Constants.DIAMETER_AVP_CC_REQUEST_NUMBER:
					int ccNum = new AVP_Unsigned32(avp).queryValue();
					dccTransRec.setCcRequestNumber(ccNum);
					break;
				case Constants.DIAMETER_AVP_ORIGIN_HOST:
					dccTransRec.setOriginHost(new AVP_UTF8String(avp).queryValue());
					break;
				case Constants.DIAMETER_AVP_DEST_HOST:
					dccTransRec.setDestHost(new AVP_UTF8String(avp).queryValue());
					break;
				case Constants.DIAMETER_AVP_DES_REALM:
					dccTransRec.setDestRealm(new AVP_UTF8String(avp).queryValue());
					break;
				case Constants.DIAMETER_AVP_RESULT_CODE:
					dccTransRec.setResultCode(new AVP_Unsigned32(avp).queryValue());
					break;
				case Constants.DIAMETER_AVP_SERVICE_RESULT_CODE:
					dccTransRec.setServiceResultCode(new AVP_Unsigned32(avp).queryValue());
					break;
				}
			} catch (InvalidAVPLengthException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 
	 * 
	 * @param cca
	 * @return CC-Request-Number
	 */
	public static void processCCAMessgeInfos(Message msg, BusinessRecord brec) {

		List<AVP> avpList = msg.getAvpList();
		// String rs;
		for (AVP avp : avpList) {
			try {
				switch (avp.code()) {
				// case Constants.DIAMETER_AVP_Route_Record:
				// rs = (new AVP_UTF8String(avp)).queryValue();
				// String routeRecord = brec.getRouteRecord();
				// if (routeRecord != null && routeRecord.length() > 0) {
				// routeRecord = routeRecord + "+" + rs;
				// } else {
				// routeRecord = rs;
				// }
				// brec.setRouteRecord(routeRecord);
				// break;
				// case Constants.DIAMETER_AVP_Forward_Info:
				// AVP_Grouped forwardInfoGrouped;
				// forwardInfoGrouped = new AVP_Grouped(avp);
				//
				// AVP selfHost =
				// forwardInfoGrouped.find(Constants.DIAMETER_AVP_SELF_HOST,
				// Constants.DIAMETER_VENDOR_CT);
				// String foInfo = "";
				// if (null != selfHost) {
				// foInfo = (new AVP_UTF8String(selfHost)).queryValue();
				// }
				// foInfo = foInfo + ":";
				// AVP downstreamHost =
				// forwardInfoGrouped.find(Constants.DIAMETER_AVP_DOWNSTREAM_HOST,
				// Constants.DIAMETER_VENDOR_CT);
				// if (null != downstreamHost) {
				// foInfo = foInfo + (new
				// AVP_UTF8String(downstreamHost)).queryValue();
				// }
				// AVP responseTime =
				// forwardInfoGrouped.find(Constants.DIAMETER_AVP_RESPONSE_TIME,
				// Constants.DIAMETER_VENDOR_CT);
				// foInfo = foInfo + ":";
				// if (null != responseTime) {
				// foInfo = foInfo + (new
				// AVP_Unsigned32(responseTime)).queryValue();
				// }
				// String forwardInfo = brec.getForwardInfo();
				// if (null != forwardInfo && forwardInfo.length() > 0) {
				// forwardInfo = forwardInfo + "+" + foInfo;
				// } else {
				// forwardInfo = foInfo;
				// }
				// brec.setForwardInfo(forwardInfo);
				// break;

				case Constants.DIAMETER_AVP_ORIGIN_HOST:
					brec.setResponseHost(AVP_UTF8String.queryValue(avp));
					break;

				case Constants.DIAMETER_AVP_RESULT_CODE:
					brec.setResultCode(AVP_Unsigned32.queryValue(avp));
					break;
				}
			} catch (InvalidAVPLengthException e) {
				e.printStackTrace();
			}

			// AVP[] avps = new AVP[avpList.size()];
			// AVP _avp = getAVP(avpList.toArray(avps),
			// Constants.DIAMETER_AVP_SERVICE_RESULT_CODE);
			// if (_avp != null) {
			// try {
			// brec.setServiceResultCode(new AVP_Unsigned32(_avp).queryValue());
			// } catch (InvalidAVPLengthException e) {
			// e.printStackTrace();
			// }
			// }
		}
	}

	public static String getCapability(Message msg) {
		String capability = "";
		AVP srvCtxAVP = msg.find(Constants.DIAMETER_AVP_SERVICE_CONTEXT_ID);
		if (srvCtxAVP != null) {
			String serviceContextId = AVP_UTF8String.queryValue(srvCtxAVP);
			capability = serviceContextId.substring(0, serviceContextId.indexOf('@'));
		}
		return capability;
	}
	
	/**
	 * 返回AVP_SERVICE_RESULT_CODE ，如果出错，返回-1
	 * 
	 * @param cca
	 * @return AVP_SERVICE_RESULT_CODE
	 */
	public static int getCCAMessageServiceResultCode(Message cca, String sessionId) {
		int result = -1;
		try {
			AVP[] avps = new AVP[cca.getAvpList().size()];
			AVP avp = getAVP(cca.getAvpList().toArray(avps), Constants.DIAMETER_AVP_SERVICE_RESULT_CODE);
			if (avp != null) {
				result = new AVP_Unsigned32(avp).queryValue();
			} else {
				logger.warn("There is no Service_Result_Code avp in session " + sessionId);
			}
		} catch (Exception e) {
			logger.warn("Exception occur when find Service_Result_Code avp in session " + sessionId, e);
		}
		return result;
	}
	
	public static String getValueByPath(Object request, String xmlTag, LinkedList<AvpType> avpPath) {
		String key = null;
		if (request instanceof XmlMessage) {
			try {
				if (xmlTag == null)
					return null;
				Element e = ((XmlMessage) request).getDataElement();
				org.dom4j.Node keyNode = e.selectSingleNode(xmlTag);
				if (keyNode != null)
					key = keyNode.getStringValue();
			} catch (Exception e) {
				logger.warn("getValueByPath exception:", e);
			}
		} else if (request instanceof Message) {
			Message m = (Message) request;
			AVP_Grouped parentGroup = null;
			AVP findAvp = null;
			try {
				if (avpPath == null || avpPath.size() <= 0)
					return null;
				for (Iterator<AvpType> it = avpPath.iterator(); it.hasNext();) {
					AvpType avpType = it.next();

					if (parentGroup == null) {
						findAvp = m.find(avpType.getCode(), avpType.getVendorId());
					} else {
						findAvp = parentGroup.find(avpType.getCode(), avpType.getVendorId());
					}
					if (findAvp == null)
						break;
					if (it.hasNext()) {
						parentGroup = new AVP_Grouped(findAvp);

					} else {
						key = AVP_UTF8String.queryValue(findAvp);
					}
				}
			} catch (InvalidAVPLengthException e1) {
				logger.warn("InvalidAVPLengthException:", e1);
			}
		}
		return key;
	}
	
	public static LinkedList<AvpType> convertXPath2AvpPath(String xmlPath) {
		if (xmlPath == null) {
			return null;
		}
		String[] paths = xmlPath.split("\\/");
		LinkedList<AvpType> avpPath = new LinkedList<AvpType>();
		for (String s : paths) {
			if (s == null || s.equals(""))
				continue;
			AvpType avpType = DictionaryManager.getInstance().avpType(4, s);
			if (avpType == null) {
				logger.warn("not find avpType:" + s);
				return null;
			} else {
				avpPath.add(avpType);
			}
		}
		return avpPath;
	}
}
